#include<iostream>

/*
在C++中，一个类是可以定义自己类型的静态对象的。
这是完全合法的语法，
因为静态成员属于类作用域而非实例作用域，不会造成无限递归的问题。
*/
//单例模式之饿汉模式--程序启动就创建一个静态对象(不会出现线程安全问题因为一旦启动程序对象就别定义好了)
//指导思想--构造函数私有化，拷贝和赋值重载禁用
//类中声明静态对象，类外定义静态对象，提供静态方法获取静态对象
//如果后面再定义静态对象则会重复定义这个静态对象，因为这个静态对象是属于类内的，只有一个。
class Singleton
{
private:
    Singleton():_data(99)
    {};
    //在类中声明一个静态对象
    static Singleton _eton;
    Singleton(const Singleton&)=delete;
    Singleton operator=(const Singleton&)=delete;
    ~Singleton(){};
public:
    int _data;
public:
    int GetData()
    {
        std::cout<<"单例模式之懒汉模式的实现"<<std::endl;
        return _data;
    }
public:
    //静态成员函数返回静态成员对象的引用
    //因为静态成员变量（如Singleton::_eton）的生命周期是整个程序运行期间，
    //它并不是临时对象。因此，返回它的引用是完全安全的。
    static Singleton &GetInstance()
    {
        return _eton;
    }

};

//类外定义静态成员
Singleton Singleton::_eton;


//懒汉模式实现单例--用的时候再创建唯一对象
//指导思想：利用静态局部变量的特性：
//‌定义位置‌：在函数或代码块内部
//‌作用域‌：仅在定义它的函数/代码块内可见
//‌生命周期‌：整个程序运行期间
//‌初始化‌：第一次执行到声明处时初始化（线程安全）
//‌访问性‌：只能被定义它的函数访问
/*
1 ‌首次初始化（关键部分）‌：
编译器会生成隐藏的线程安全保护代码（类似原子操作+互斥锁）
只有一个线程能真正执行初始化，其他线程会被阻塞
初始化完成后，保护机制立即解除
‌后续执行（所有线程）‌：

2 直接跳过初始化语句
仅读取已初始化的变量（无锁操作，高性能）
表现为普通的变量访问
*/

class Singleton1
{
private:
    Singleton1():_data(99)
    {};
    Singleton1(const Singleton&)=delete;
    Singleton1 operator=(const Singleton&)=delete;
    ~Singleton1(){};
public:
    int _data;
public:
    int GetData()
    {
        std::cout<<"单例模式懒汉方式的实现"<<std::endl;
        return _data;
    }
public:
    //静态成员函数返回静态成员对象的引用
    //因为静态成员变量（如Singleton::_eton）的生命周期是整个程序运行期间，
    //它并不是临时对象。因此，返回它的引用是完全安全的。
    static Singleton1 &GetInstance()
    {
        //定义一个局部的静态变量
        static Singleton1 _eton1;
        return _eton1;
    }

};

int main()
{
    //std::cout<<Singleton::GetInstance().GetData()<<std::endl;
    std::cout<<Singleton1::GetInstance().GetData()<<std::endl;
    return 0;
}
